<?php

class Tools {
	//put your code here
	
	
	public static function checkPath($filename, $svn_path) {
		return substr($filename, strlen($svn_path)+1);
	}
	
	
	public static function checkExclude($str, $array=array()) {
		foreach($array as $a) {
			$pattern = '#^'. preg_quote($a) .'#is';
			if (preg_match($pattern, $str)) return true;
		}
		
		return false;
	}

	/**
	 * 获得上传文件列表
	 * @param string $uploadIds	//id
	 * @param Project $project	//模型
	 * @return array
	 */
	public static function getUploadFileList($uploadIds, $project) {

		$uploads = Upload::model()->findAll(array(
				'condition'=>'uploadId in ('. $uploadIds .')'
		));
		$files = array();
		$exclude = array();
		if (trim($project->noPubList)!='') {
			$opts = explode("\n", $project->noPubList);
			if (is_array($opts)) {
				foreach($opts as $opt) {
					$exclude[] = trim($opt);
				}
			}
		}
		
		if (is_array($uploads) && count($uploads)>0) {
			foreach($uploads as $upload) {
				$filename = self::checkPath($upload->filename, $project->svnProjectName);
				if (!self::checkExclude($filename, $exclude))
					$files[]=$filename;
			}
		}
		
		return $files;
	}
	
	/**
	 * 获得上传文件列表
	 * @param string $uploadIds	//id
	 * @param Project $project	//模型
	 * @return array
	 */
	public static function getPublishFileList($uploadIds, $project) {
	
		$uploads = Publish::model()->findAll(array(
				'condition'=>'pubId in ('. $uploadIds .')'
		));
		$files = array();
		$exclude = array();
		if (trim($project->noPubList)!='') {
			$opts = explode("\n", $project->noPubList);
			if (is_array($opts)) {
				foreach($opts as $opt) {
					$exclude[] = trim($opt);
				}
			}
		}
	
		if (is_array($uploads) && count($uploads)>0) {
			foreach($uploads as $upload) {
				$filename = self::checkPath($upload->filename, $project->svnProjectName);
				if (!self::checkExclude($filename, $exclude))
					$files[]=$filename;
			}
		}
	
		return $files;
	}
	
	/**
	 * 
	 * @param string $archive	//档案名
	 * @param string $archivesPath //本地档案路径
	 * @param Project $project
	 * @param array $files
	 * @return string
	 */
	public static function tar($archive, $files, $project) {
		$svnDataPath = Yii::app()->params['svnDataPath'].'/'.$project->projectId;
		$archivesPath = Yii::app()->params['archivesPath'];
		if (!is_dir($archivesPath)) {
			@mkdir($archivesPath);
		}
		
		if (!is_dir($archivesPath) || !is_writable($archivesPath)) return '档案路径不可写';
		//pear install Archive_Tar
		include ('Archive/Tar.php');// import class
		
		$tar = new Archive_Tar("$archivesPath/$archive"); // name of TAR file
		@chdir($svnDataPath);
		$tar->add($files);
		return '';
	}
	
	/**
	 * 更新svn
	 * @param Project $project
	 * @return string
	 */
	public static function svnUpdate($project) {
		$message = '';
		$svnDataPath = Yii::app()->params['svnDataPath'].'/'.$project->projectId;
		if ($project->svnUser!='' && $project->svnPass!='') {
			$svn = new ESvn($project->svnUser, $project->svnPass);
		}
		else $svn = new ESvn;
		
		if (!is_dir($svnDataPath."/.svn") && !is_dir($svnDataPath)) {
			@mkdir($svnDataPath);
			if (!is_dir($svnDataPath) || !is_writable($svnDataPath)) return 'SVN数据路径不可写';
			
			$return  = $svn->co($project->svnProjectPath, $svnDataPath);
			if (!$return) {
				@rmdir($svnDataPath);
				return 'SVN地址不正确';
			}
		}
		else {
			//echo $svnDataPath;
			$return = @$svn->update($svnDataPath);
			if (!$return) {
				return 'SVN更新出错';
			}
		}
	
		return $message;

	}
	
	/**
	 * ajax错误返回
	 * @param string $message
	 */
	public static function ajaxErrorReturn($message) {
		$return = array();
		$return['error'] = $message;
		echo CJSON::encode($return);
		exit;
	}
	
	/**
	 * 发送打包文件 到发布服务器
	 * @param type $filetag
	 * @param type $archives_path  LOCAL archvie file path
	 * @param type $archvie LOCAL archvie filename
	 * @param Host $modelHost 
	 * @param Project $modelProject 项目模型
	 * @param boolean $rollback 
	 */

	
	
	/**
	 * 
	 * @param string $fileTag		//
	 * @param string $archive		//档案名
	 * @param Host $host			//主机模型
	 * @param Project $project		//项目模型
	 * @param boolean $isUpload		//是否上传
	 * @param boolean $rollback	//是否为回滚
	 * @return string
	 */
	public static function sendUpload($fileTag, $archive, $host, $project, $isUpload=true, $rollback=false) {
		$archivesPath = Yii::app()->params['archivesPath'];
		if (!is_dir($archivesPath)) {
			@mkdir($archivesPath);
		}
		
		if (!is_dir($archivesPath) || !is_writable($archivesPath)) return '档案路径不可写';
		
		$scriptPath =Yii::app()->params['scriptPath'];
		if (!is_dir($scriptPath)) {
			@mkdir($scriptPath);
			if (!is_dir($scriptPath) || !is_writable($scriptPath)) return '脚本存放路径不可写';
		}
		
		$projectId = $project->projectId;
		
		$tmpPath = $host->tmpPath;
		$archivePath = $host->archivePath; //线上档案目录
		$logPath = $host->scriptLogPath;	//脚本执行路径
		$sendStatus = $host->sendStatus;	//代码是否在跳板机发送
		$logName = "P".$project->projectId ."_".date("Y-m-d").".log";
		$logFile = $logPath."/".$logName;

		$rsyncPackage = "$archivePath/$archive";		//线上传的服务器档案
	
	
		//创建发布脚本
		//线上打包 目录
	
		$deleteFiles = '';
		if ($rollback==true)
			$deleteFiles = '';
		else {
			if ($project->isRemove!=0) {
				//获取SVN中移除的文件
				$deleteFiles = array();
				$deletes = Yii::app()->db->createCommand()->from('{{upload}}')
				->select('uploadId, filename')
				->where('projectId=? AND status="D"', array($projectId))
				->queryAll();
				$deleteFileIds = array();
	
				foreach($deletes as $delete) {
					$deleteFileIds[] = $delete['uploadId'];
					$deleteFiles[] = "/bin/rm -rf ". Tools::checkPath($delete['filename'], $project->svnProjectName);
				}
				$deleteFiles = join(" && ", $deleteFiles);
			}
		}
	
		$rsync = array();	//rsync -zvrtopg -e ‘ssh -p 端口'
		//获取分发服务器
		$distributes = $host->distributes;
		if (is_array($distributes) && count($distributes)>0) {	//有分发服务器，制作同步脚本
	
			foreach($distributes as $dh) {
				$rsync[] = "echo '**** BEGIN SCP ". $dh->host ." ****'";	//主机
				$rsync[] = "echo '' ";
				$rsync[] = "scp -P ". $dh->port ." $rsyncPackage ". $dh->host. ":". $dh->archivePath ;	//拷贝包到分发服务器
				$rsync[] = "echo '' ";
				$rsync[] = "echo '**** END SCP ". $dh->host ." ****'";
	
				$rsync[] = "echo '**** BEGIN UNTAR ". $dh->host ." ****'";
				$rsync[] = "echo '' ";
				$destPackage = $dh->archivePath.'/'.$archive;
				$rsync[] = "ssh ". $dh->host ." \" cd ". $dh->pubPath ." && tar -xvf $destPackage \"";	//解压到发布目录
				$rsync[] = "echo '' ";
				$rsync[] = "echo '**** END UNTAR ". $dh->host ." ****'";
	
				$rsync[] = "echo '**** BEGIN RMTAR ". $dh->host ." ****'";
				$rsync[] = "echo '' ";
				$rsync[] = "ssh ". $dh->host ." \" rm -rf $destPackage \"";	//删除分发服务器上的包
				$rsync[] = "echo '' ";
				$rsync[] = "echo '**** END RMTAr ". $dh->host ." ****'";
	
				if ($deleteFiles!="") {
					$rsync[] = "echo '**** BEGIN RMSVNFILE ". $dh->host ." ****'";
					$rsync[] = "echo '' ";
					$rsync[] = "ssh ". $dh->host ." \" cd ". $dh->pubPath ." && ". $deleteFiles ." \"";	//删除分发服务器上的包
					$rsync[] = "echo '' ";
					$rsync[] = "echo '**** END RMSVNFILE ". $dh->host ." ****'";
				}
			}
		}
	
	
		$rsync = join("\n", $rsync);
		if (trim($rsync)!='') $rsync = 'if [ -f '. $rsyncPackage ." ]; then\n".$rsync."\nfi\n";
	
		$scriptTemplate=file_get_contents(Yii::getPathOfAlias('application.data').'/pub-script');
		$scriptTemplate=strtr($scriptTemplate, array(
				'{{packagename}}' => $rsyncPackage,
				'{{pub_path}}' => $host->pubPath,
				'{{rsync}}' => $rsync,
				'{{deletefiles}}' => $deleteFiles,
				'{{sendStatus}}'	=>	$sendStatus
		));
	
		$pubScript="P".$projectId."_".$fileTag.".sh";
		$pubScriptPath = $scriptPath."/$pubScript";
		file_put_contents($pubScriptPath, $scriptTemplate);
		
		
		//拷贝打包文件到发布主机
		//SSH发送文件
		$ssh = new ESsh($host->host, $host->port, $host->username, $host->password);
		if ($ssh==null) return '无法连接发布主机';
		
		$ssh->exec("echo '-----". date("Y-m-d H:i:s") ." UPLOAD ------' >> $logFile");
		$return = $ssh->scp("$archivesPath/$archive", "$rsyncPackage",0775);
		if (!$return) return '无法发送文件到发布主机';
	
		$ssh->scp($pubScriptPath, "$tmpPath/$pubScript", 0775);	//放到临时目录
		$ssh->exec("/bin/sh $tmpPath/$pubScript >> $logFile");
		$ssh->exec("echo '-------------END UPLOAD -----------------' >> $logFile");
	
		#$ssh->exec("/bin/rm -rf $rsyncPackage && /bin/rm -rf $tmpPath/$pubScript");
		if ($isUpload) {
			@unlink($pubScriptPath);
		}
	
		if ($project->isRemove==1 && isset($deleteFileIds) && count($deleteFileIds)>0) {
			Yii::app()->db->createCommand()->delete('{{upload}}', 'uploadId in ('. join(",", $deleteFileIds) .')');
		}
		
		
		return '';
	}
}

?>
